home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d13
/
phantz.arc
/
PHANT3.Z
/
PHANT3
Wrap
Text File
|
1991-06-06
|
62KB
|
2,428 lines
: ---------CUT HERE---------
: This is a shar archive. Extract with sh, not csh.
: The rest of this file will extract:
: interplayer.c gamesupport.c io.c
echo x - interplayer.c
sed 's/^X//' > interplayer.c << '!EOR!'
X/*
X * interplayer.c - player to player routines for Phantasia
X */
X
X#include "include.h"
X
X/************************************************************************
X/
X/ FUNCTION NAME: checkbattle()
X/
X/ FUNCTION: check to see if current player should battle another
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: battleplayer(), fread(), fseek()
X/
X/ GLOBAL INPUTS: Other, Users, Player, Fileloc, *Playersfp
X/
X/ GLOBAL OUTPUTS: Users
X/
X/ DESCRIPTION:
X/ Seach player file for a foe at the same coordinates as the
X/ current player.
X/ Also update user count.
X/
X/************************************************************************/
X
Xcheckbattle()
X{
Xlong foeloc = 0L; /* location in file of person to fight */
X
X Users = 0;
X fseek(Playersfp, 0L, 0);
X
X while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
X {
X if (Other.p_status != S_OFF
X && Other.p_status != S_NOTUSED
X && Other.p_status != S_HUNGUP
X && (Other.p_status != S_CLOAKED || Other.p_specialtype != SC_VALAR))
X /* player is on and not a cloaked valar */
X {
X ++Users;
X
X if (Player.p_x == Other.p_x
X && Player.p_y == Other.p_y
X /* same coordinates */
X && foeloc != Fileloc
X /* not self */
X && Player.p_status == S_PLAYING
X && (Other.p_status == S_PLAYING || Other.p_status == S_INBATTLE)
X /* both are playing */
X && Other.p_specialtype != SC_VALAR
X && Player.p_specialtype != SC_VALAR)
X /* neither is valar */
X {
X battleplayer(foeloc);
X return;
X }
X }
X foeloc += SZ_PLAYERSTRUCT;
X }
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: battleplayer()
X/
X/ FUNCTION: inter-terminal battle with another player
X/
X/ AUTHOR: E. A. Estes, 2/15/86
X/
X/ ARGUMENTS:
X/ long foeplace - location in player file of person to battle
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: readrecord(), readmessage(), writerecord(), collecttaxes(),
X/ displaystats(), fabs(), more(), death(), sleep(), wmove(), waddch(), printw(),
X/ myturn(), altercoordinates(), waddstr(), wrefresh(), mvprintw(),
X/ getanswer(), wclrtoeol(), wclrtobot()
X/
X/ GLOBAL INPUTS: Foestrikes, LINES, Lines, Other, Shield, Player, *stdscr,
X/ Fileloc, *Enemyname
X/
X/ GLOBAL OUTPUTS: Foestrikes, Lines, Shield, Player, Luckout, *Enemyname
X/
X/ DESCRIPTION:
X/ Inter-terminal battle is a very fragile and slightly klugy thing.
X/ At any time, one player is master and the other is slave.
X/ We pick who is master first by speed and level. After that,
X/ the slave waits for the master to relinquish its turn, and
X/ the slave becomes master, and so on.
X/
X/ The items in the player structure which control the handshake are:
X/ p_tampered:
X/ master increments this to relinquish control
X/ p_istat:
X/ master sets this to specify particular action
X/ p_1scratch:
X/ set to total damage inflicted so far; changes to indicate action
X/
X/************************************************************************/
X
Xbattleplayer(foeplace)
Xlong foeplace;
X{
Xdouble dtemp; /* for temporary calculations */
Xdouble oldhits = 0.0; /* previous damage inflicted by foe */
Xregister int loop; /* for timing out */
Xint ch; /* input */
Xshort oldtampered; /* old value of foe's p_tampered */
X
X Lines = 8;
X Luckout = FALSE;
X mvaddstr(4, 0, "Preparing for battle!\n");
X refresh();
X
X#ifdef SYS5
X flushinp();
X#endif
X
X /* set up variables, file, etc. */
X Player.p_status = S_INBATTLE;
X Shield = Player.p_energy;
X
X /* if p_tampered is not 0, someone else may try to change it (king, etc.) */
X Player.p_tampered = oldtampered = 1;
X Player.p_1scratch = 0.0;
X Player.p_istat = I_OFF;
X
X readrecord(&Other, foeplace);
X if (fabs(Player.p_level - Other.p_level) > 20.0)
X /* see if players are greatly mismatched */
X {
X dtemp = (Player.p_level - Other.p_level) / MAX(Player.p_level, Other.p_level);
X if (dtemp < -0.5)
X /* foe outweighs this one */
X Player.p_speed *= 2.0;
X }
X
X writerecord(&Player, Fileloc); /* write out all our info */
X
X if (Player.p_blindness)
X Enemyname = "someone";
X else
X Enemyname = Other.p_name;
X
X mvprintw(6, 0, "You have encountered %s Level: %.0f\n", Enemyname, Other.p_level);
X refresh();
X
X for (loop = 0; Other.p_status != S_INBATTLE && loop < 30; ++loop)
X /* wait for foe to respond */
X {
X readrecord(&Other, foeplace);
X sleep(1);
X }
X
X if (Other.p_status != S_INBATTLE)
X /* foe did not respond */
X {
X mvprintw(5, 0, "%s is not responding.\n", Enemyname);
X goto LEAVE;
X }
X /* else, we are ready to battle */
X
X move(4, 0);
X clrtoeol();
X
X /*
X * determine who is first master
X * if neither player is faster, check level
X * if neither level is greater, battle is not allowed
X * (this should never happen, but we have to handle it)
X */
X if (Player.p_speed > Other.p_speed)
X Foestrikes = FALSE;
X else if (Other.p_speed > Player.p_speed)
X Foestrikes = TRUE;
X else if (Player.p_level > Other.p_level)
X Foestrikes = FALSE;
X else if (Other.p_level > Player.p_level)
X Foestrikes = TRUE;
X else
X /* no one is faster */
X {
X printw("You can't fight %s yet.", Enemyname);
X goto LEAVE;
X }
X
X for (;;)
X {
X displaystats();
X readmessage();
X mvprintw(1, 26, "%20.0f", Shield); /* overprint energy */
X
X if (!Foestrikes)
X /* take action against foe */
X myturn();
X else
X /* wait for foe to take action */
X {
X mvaddstr(4, 0, "Waiting...\n");
X clrtoeol();
X refresh();
X
X for (loop = 0; loop < 20; ++loop)
X /* wait for foe to act */
X {
X readrecord(&Other, foeplace);
X if (Other.p_1scratch != oldhits)
X /* p_1scratch changes to indicate action */
X break;
X else
X /* wait and try again */
X {
X sleep(1);
X addch('.');
X refresh();
X }
X }
X
X if (Other.p_1scratch == oldhits)
X {
X /* timeout */
X mvaddstr(22, 0, "Timeout: waiting for response. Do you want to wait ? ");
X ch = getanswer("NY", FALSE);
X move(22, 0);
X clrtobot();
X if (ch == 'Y')
X continue;
X else
X break;
X }
X else
X /* foe took action */
X {
X switch (Other.p_istat)
X {
X case I_RAN: /* foe ran away */
X mvprintw(Lines++, 0, "%s ran away!", Enemyname);
X break;
X
X case I_STUCK: /* foe tried to run, but couldn't */
X mvprintw(Lines++, 0, "%s tried to run away.", Enemyname);
X break;
X
X case I_BLEWIT: /* foe tried to luckout, but didn't */
X mvprintw(Lines++, 0, "%s tried to luckout!", Enemyname);
X break;
X
X default:
X dtemp = Other.p_1scratch - oldhits;
X mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, dtemp);
X Shield -= dtemp;
X break;
X }
X
X oldhits = Other.p_1scratch; /* keep track of old hits */
X
X if (Other.p_tampered != oldtampered)
X /* p_tampered changes to relinquish turn */
X {
X oldtampered = Other.p_tampered;
X Foestrikes = FALSE;
X }
X }
X }
X
X /* decide what happens next */
X refresh();
X if (Lines > LINES - 2)
X {
X more(Lines);
X move(Lines = 8, 0);
X clrtobot();
X }
X
X if (Other.p_istat == I_KILLED || Shield < 0.0)
X /* we died */
X {
X Shield = -2.0; /* insure this value is negative */
X break;
X }
X
X if (Player.p_istat == I_KILLED)
X /* we killed foe; award treasre */
X {
X mvprintw(Lines++, 0, "You killed %s!", Enemyname);
X Player.p_experience += Other.p_experience;
X Player.p_crowns += (Player.p_level < 1000.0) ? Other.p_crowns : 0;
X Player.p_amulets += Other.p_amulets;
X Player.p_charms += Other.p_charms;
X collecttaxes(Other.p_gold, Other.p_gems);
X Player.p_sword = MAX(Player.p_sword, Other.p_sword);
X Player.p_shield = MAX(Player.p_shield, Other.p_shield);
X Player.p_quksilver = MAX(Player.p_quksilver, Other.p_quksilver);
X if (Other.p_virgin && !Player.p_virgin)
X {
X mvaddstr(Lines++, 0, "You have rescued a virgin. Will you be honorable ? ");
X if ((ch = getanswer("YN", FALSE)) == 'Y')
X Player.p_virgin = TRUE;
X else
X {
X ++Player.p_sin;
X Player.p_experience += 8000.0;
X }
X }
X sleep(3); /* give other person time to die */
X break;
X }
X else if (Player.p_istat == I_RAN || Other.p_istat == I_RAN)
X /* either player ran away */
X break;
X }
X
XLEAVE:
X /* clean up things and leave */
X writerecord(&Player, Fileloc); /* update a final time */
X altercoordinates(0.0, 0.0, A_NEAR); /* move away from battle site */
X Player.p_energy = Shield; /* set energy to actual value */
X Player.p_tampered = T_OFF; /* clear p_tampered */
X
X more(Lines); /* pause */
X
X move(4, 0);
X clrtobot(); /* clear bottom area of screen */
X
X if (Player.p_energy < 0.0)
X /* we are dead */
X death("Interterminal battle");
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: myturn()
X/
X/ FUNCTION: process players action against foe in battle
X/
X/ AUTHOR: E. A. Estes, 2/7/86
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: writerecord(), inputoption(), floor(), wmove(), random(),
X/ waddstr(), wrefresh(), mvprintw(), wclrtoeol(), wclrtobot()
X/
X/ GLOBAL INPUTS: Lines, Other, Player, *stdscr, Fileloc, Luckout,
X/ *Enemyname
X/
X/ GLOBAL OUTPUTS: Foestrikes, Lines, Player, Luckout
X/
X/ DESCRIPTION:
X/ Take action action against foe, and decide who is master
X/ for next iteration.
X/
X/************************************************************************/
X
Xmyturn()
X{
Xdouble dtemp; /* for temporary calculations */
Xint ch; /* input */
X
X mvaddstr(7, 0, "1:Fight 2:Run Away! 3:Power Blast ");
X if (Luckout)
X clrtoeol();
X else
X addstr("4:Luckout ");
X
X ch = inputoption();
X move(Lines = 8, 0);
X clrtobot();
X
X switch (ch)
X {
X default: /* fight */
X dtemp = ROLL(2.0, Player.p_might);
XHIT:
X mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, dtemp);
X Player.p_sin += 0.5;
X Player.p_1scratch += dtemp;
X Player.p_istat = I_OFF;
X break;
X
X case '2': /* run away */
X Player.p_1scratch -= 1.0; /* change this to indicate action */
X if (random() > 0.25)
X {
X mvaddstr(Lines++, 0, "You got away!");
X Player.p_istat = I_RAN;
X }
X else
X {
X mvprintw(Lines++, 0, "%s is still after you!", Enemyname);
X Player.p_istat = I_STUCK;
X }
X break;
X
X case '3': /* power blast */
X dtemp = MIN(Player.p_mana, Player.p_level * 5.0);
X Player.p_mana -= dtemp;
X dtemp *= (random() + 0.5) * Player.p_magiclvl * 0.2 + 2.0;
X mvprintw(Lines++, 0, "You blasted %s !", Enemyname);
X goto HIT;
X
X case '4': /* luckout */
X if (Luckout || random() > 0.1)
X {
X if (Luckout)
X mvaddstr(Lines++, 0, "You already tried that!");
X else
X {
X mvaddstr(Lines++, 0, "Not this time . . .");
X Luckout = TRUE;
X }
X
X Player.p_1scratch -= 1.0;
X Player.p_istat = I_BLEWIT;
X }
X else
X {
X mvaddstr(Lines++, 0, "You just lucked out!");
X Player.p_1scratch = Other.p_energy * 1.1;
X }
X break;
X }
X
X refresh();
X Player.p_1scratch = floor(Player.p_1scratch); /* clean up any mess */
X
X if (Player.p_1scratch > Other.p_energy)
X Player.p_istat = I_KILLED;
X else if (random() * Player.p_speed < random() * Other.p_speed)
X /* relinquish control */
X {
X ++Player.p_tampered;
X Foestrikes = TRUE;
X }
X
X writerecord(&Player, Fileloc); /* let foe know what we did */
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: checktampered()
X/
X/ FUNCTION: check if current player has been tampered with
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: readrecord(), fread(), fseek(), tampered(), writevoid()
X/
X/ GLOBAL INPUTS: *Energyvoidfp, Other, Player, Fileloc, Enrgyvoid
X/
X/ GLOBAL OUTPUTS: Enrgyvoid
X/
X/ DESCRIPTION:
X/ Check for energy voids, holy grail, and tampering by other
X/ players.
X/
X/************************************************************************/
X
Xchecktampered()
X{
Xlong loc = 0L; /* location in energy void file */
X
X /* first check for energy voids */
X fseek(Energyvoidfp, 0L, 0);
X while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
X if (Enrgyvoid.ev_active
X && Enrgyvoid.ev_x == Player.p_x
X && Enrgyvoid.ev_y == Player.p_y)
X /* sitting on one */
X {
X if (loc > 0L)
X /* not the holy grail; inactivate energy void */
X {
X Enrgyvoid.ev_active = FALSE;
X writevoid(&Enrgyvoid, loc);
X tampered(T_NRGVOID, 0.0, 0.0);
X }
X else if (Player.p_status != S_CLOAKED)
X /* holy grail */
X tampered(T_GRAIL, 0.0, 0.0);
X break;
X }
X else
X loc += SZ_VOIDSTRUCT;
X
X /* now check for other things */
X readrecord(&Other, Fileloc);
X if (Other.p_tampered != T_OFF)
X tampered(Other.p_tampered, Other.p_1scratch, Other.p_2scratch);
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: tampered()
X/
X/ FUNCTION: take care of tampering by other players
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS:
X/ int what - what type of tampering
X/ double arg1, arg2 - rest of tampering info
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: writerecord(), more(), fread(), death(), fseek(), sleep(),
X/ floor(), wmove(), waddch(), random(), printw(), altercoordinates(),
X/ waddstr(), wrefresh(), encounter(), writevoid()
X/
X/ GLOBAL INPUTS: Other, Player, *stdscr, Enrgyvoid, *Playersfp
X/
X/ GLOBAL OUTPUTS: Other, Player, Changed, Enrgyvoid
X/
X/ DESCRIPTION:
X/ Take care of energy voids, holy grail, decree and intervention
X/ action on current player.
X/
X/************************************************************************/
X
Xtampered(what, arg1, arg2)
Xint what;
Xdouble arg1;
Xdouble arg2;
X{
Xlong loc; /* location in file of other players */
X
X Changed = TRUE;
X move(4,0);
X
X Player.p_tampered = T_OFF; /* no longer tampered with */
X
X switch (what)
X {
X case T_NRGVOID:
X addstr("You've hit an energy void !\n");
X Player.p_mana /= 3.0;
X Player.p_energy /= 2.0;
X Player.p_gold = floor(Player.p_gold/1.25) + 0.1;
X altercoordinates(0.0, 0.0, A_NEAR);
X break;
X
X case T_TRANSPORT:
X addstr("The king transported you ! ");
X if (Player.p_charms > 0)
X {
X addstr("But your charm save you. . .\n");
X --Player.p_charms;
X }
X else
X {
X altercoordinates(0.0, 0.0, A_FAR);
X addch('\n');
X }
X break;
X
X case T_BESTOW:
X printw("The king has bestowed %.0f gold pieces on you !\n", arg1);
X Player.p_gold += arg1;
X break;
X
X case T_CURSED:
X addstr("You've been cursed ! ");
X if (Player.p_blessing)
X {
X addstr("But your blessing saved you. . .\n");
X Player.p_blessing = FALSE;
X }
X else
X {
X addch('\n');
X Player.p_poison += 2.0;
X Player.p_energy = 10.0;
X Player.p_maxenergy *= 0.95;
X Player.p_status = S_PLAYING; /* no longer cloaked */
X }
X break;
X
X case T_VAPORIZED:
X addstr("You have been vaporized!\n");
X more(7);
X death("Vaporization");
X break;
X
X case T_MONSTER:
X addstr("The Valar zapped you with a monster!\n");
X more(7);
X encounter((int) arg1);
X return;
X
X case T_BLESSED:
X addstr("The Valar has blessed you!\n");
X Player.p_energy = (Player.p_maxenergy *= 1.05) + Player.p_shield;
X Player.p_mana += 500.0;
X Player.p_strength += 0.5;
X Player.p_brains += 0.5;
X Player.p_magiclvl += 0.5;
X Player.p_poison = MIN(0.5, Player.p_poison);
X break;
X
X case T_RELOCATE:
X addstr("You've been relocated. . .\n");
X altercoordinates(arg1, arg2, A_FORCED);
X break;
X
X case T_HEAL:
X addstr("You've been healed!\n");
X Player.p_poison -= 0.25;
X Player.p_energy = Player.p_maxenergy + Player.p_shield;
X break;
X
X case T_EXVALAR:
X addstr("You are no longer Valar!\n");
X Player.p_specialtype = SC_COUNCIL;
X break;
X
X case T_GRAIL:
X addstr("You have found The Holy Grail!!\n");
X if (Player.p_specialtype < SC_COUNCIL)
X /* must be council of wise to behold grail */
X {
X addstr("However, you are not experienced enough to behold it.\n");
X Player.p_sin *= Player.p_sin;
X Player.p_mana += 1000;
X }
X else if (Player.p_specialtype == SC_VALAR
X || Player.p_specialtype == SC_EXVALAR)
X {
X addstr("You have made it to the position of Valar once already.\n");
X addstr("The Grail is of no more use to you now.\n");
X }
X else
X {
X addstr("It is now time to see if you are worthy to behold it. . .\n");
X refresh();
X sleep(4);
X
X if (random() / 2.0 < Player.p_sin)
X {
X addstr("You have failed!\n");
X Player.p_strength =
X Player.p_mana =
X Player.p_energy =
X Player.p_maxenergy =
X Player.p_magiclvl =
X Player.p_brains =
X Player.p_experience =
X Player.p_quickness = 1.0;
X
X altercoordinates(1.0, 1.0, A_FORCED);
X Player.p_level = 0.0;
X }
X else
X {
X addstr("You made to position of Valar!\n");
X Player.p_specialtype = SC_VALAR;
X Player.p_lives = 5;
X fseek(Playersfp, 0L, 0);
X loc = 0L;
X while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
X /* search for existing valar */
X if (Other.p_specialtype == SC_VALAR
X && Other.p_status != S_NOTUSED)
X /* found old valar */
X {
X Other.p_tampered = T_EXVALAR;
X writerecord(&Other, loc);
X break;
X }
X else
X loc += SZ_PLAYERSTRUCT;
X }
X }
X
X /* move grail to new location */
X Enrgyvoid.ev_active = TRUE;
X Enrgyvoid.ev_x = ROLL(-1e6, 2e6);
X Enrgyvoid.ev_y = ROLL(-1e6, 2e6);
X writevoid(&Enrgyvoid, 0L);
X break;
X }
X refresh();
X sleep(2);
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: userlist()
X/
X/ FUNCTION: print list of players and locations
X/
X/ AUTHOR: E. A. Estes, 2/28/86
X/
X/ ARGUMENTS:
X/ bool ingameflag - set if called while playing
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: descrstatus(), descrlocation(), more(), fread(), fseek(),
X/ floor(), wmove(), printw(), waddstr(), distance(), wrefresh(),
X/ descrtype(), wclrtobot()
X/
X/ GLOBAL INPUTS: LINES, Other, Circle, Wizard, Player, *stdscr, *Playersfp
X/
X/ GLOBAL OUTPUTS: none
X/
X/ DESCRIPTION:
X/ We can only see the coordinate of those closer to the origin
X/ from us.
X/ Kings and council of the wise can see and can be seen by everyone.
X/ Palantirs are good for seeing everyone; and the valar can use
X/ one to see through a 'cloak' spell.
X/ The valar has no coordinates, and is completely invisible if
X/ cloaked.
X/
X/************************************************************************/
X
Xuserlist(ingameflag)
Xbool ingameflag;
X{
Xregister int numusers = 0; /* number of users on file */
X
X if (ingameflag && Player.p_blindness)
X {
X mvaddstr(8, 0, "You cannot see anyone.\n");
X return;
X }
X
X fseek(Playersfp, 0L, 0);
X mvaddstr(8, 0,
X "Name X Y Lvl Type Login Status\n");
X
X while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
X {
X if (Other.p_status == S_NOTUSED
X /* record is unused */
X || (Other.p_specialtype == SC_VALAR && Other.p_status == S_CLOAKED))
X /* cloaked valar */
X {
X if (!Wizard)
X /* wizard can see everything on file */
X continue;
X }
X
X ++numusers;
X
X if (ingameflag &&
X /* must be playing for the rest of these conditions */
X (Player.p_specialtype >= SC_KING
X /* kings and higher can see others */
X || Other.p_specialtype >= SC_KING
X /* kings and higher can be seen by others */
X || Circle >= CIRCLE(Other.p_x, Other.p_y)
X /* those nearer the origin can be seen */
X || Player.p_palantir)
X /* palantir enables one to see others */
X && (Other.p_status != S_CLOAKED
X || (Player.p_specialtype == SC_VALAR && Player.p_palantir))
X /* not cloaked; valar can see through cloak with a palantir */
X && Other.p_specialtype != SC_VALAR)
X /* not a valar */
X /* coordinates should be printed */
X printw("%-20s %8.0f %8.0f ",
X Other.p_name, Other.p_x, Other.p_y);
X else
X /* cannot see player's coordinates */
X printw("%-20s %19.19s ",
X Other.p_name, descrlocation(&Other, TRUE));
X
X printw("%6.0f %s %-9.9s%s\n", Other.p_level, descrtype(&Other, TRUE),
X Other.p_login, descrstatus(&Other));
X
X if ((numusers % (LINES - 10)) == 0)
X {
X more(LINES - 1);
X move(9, 0);
X clrtobot();
X }
X }
X
X printw("Total players on file = %d\n", numusers);
X refresh();
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: throneroom()
X/
X/ FUNCTION: king stuff upon entering throne
X/
X/ AUTHOR: E. A. Estes, 12/16/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: writerecord(), fread(), fseek(), fopen(), wmove(), fclose(),
X/ fwrite(), altercoordinates(), waddstr(), fprintf()
X/
X/ GLOBAL INPUTS: *Energyvoidfp, Other, Player, *stdscr, Voidfile[],
X/ Messfile[], Enrgyvoid, *Playersfp
X/
X/ GLOBAL OUTPUTS: Other, Player, Changed
X/
X/ DESCRIPTION:
X/ If player is not already king, make him/her so if the old king
X/ is not playing.
X/ Clear energy voids with new king.
X/ Print 'decree' prompt.
X/
X/************************************************************************/
X
Xthroneroom()
X{
XFILE *fp; /* to clear energy voids */
Xlong loc = 0L; /* location of old king in player file */
X
X if (Player.p_specialtype < SC_KING)
X /* not already king -- assumes crown */
X {
X fseek(Playersfp, 0L, 0);
X while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
X if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED)
X /* found old king */
X {
X if (Other.p_status != S_OFF)
X /* old king is playing */
X {
X mvaddstr( 4, 0, "The king is playing, so you cannot steal his throne\n");
X altercoordinates(0.0, 0.0, A_NEAR);
X move(6, 0);
X return;
X }
X else
X /* old king is not playing - remove him/her */
X {
X Other.p_specialtype = SC_NONE;
X if (Other.p_crowns)
X --Other.p_crowns;
X writerecord(&Other, loc);
X break;
X }
X }
X else
X loc += SZ_PLAYERSTRUCT;
X
X /* make player new king */
X Changed = TRUE;
X Player.p_specialtype = SC_KING;
X mvaddstr(4, 0, "You have become king!\n");
X
X /* let everyone else know */
X fp = fopen(Messfile, "w");
X fprintf(fp, "All hail the new king!");
X fclose(fp);
X
X /* clear all energy voids; retain location of holy grail */
X fseek(Energyvoidfp, 0L, 0);
X fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
X fp = fopen(Voidfile, "w");
X fwrite((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, fp);
X fclose(fp);
X }
X
X mvaddstr(6, 0, "0:Decree ");
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: dotampered()
X/
X/ FUNCTION: king and valar special options
X/
X/ AUTHOR: E. A. Estes, 2/28/86
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: writerecord(), truncstring(), fread(), fseek(), fopen(),
X/ floor(), wmove(), random(), fclose(), fwrite(), sscanf(), strcmp(),
X/ infloat(), waddstr(), findname(), distance(), userlist(), mvprintw(),
X/ allocvoid(), getanswer(), getstring(), wclrtoeol(), writevoid()
X/
X/ GLOBAL INPUTS: *Energyvoidfp, Other, Illcmd[], Wizard, Player, *stdscr,
X/ Databuf[], Goldfile[], Enrgyvoid
X/
X/ GLOBAL OUTPUTS: Other, Player, Enrgyvoid
X/
X/ DESCRIPTION:
X/ Tamper with other players. Handle king/valar specific options.
X/
X/************************************************************************/
X
Xdotampered()
X{
Xshort tamper; /* value for tampering with other players */
Xchar *option; /* pointer to option description */
Xdouble temp1 = 0.0, temp2 = 0.0; /* other tampering values */
Xint ch; /* input */
Xlong loc; /* location in energy void file */
XFILE *fp; /* for opening gold file */
X
X move(6, 0);
X clrtoeol();
X if (Player.p_specialtype < SC_COUNCIL && !Wizard)
X /* king options */
X {
X addstr("1:Transport 2:Curse 3:Energy Void 4:Bestow 5:Collect Taxes ");
X
X ch = getanswer(" ", TRUE);
X move(6, 0);
X clrtoeol();
X move(4, 0);
X switch (ch)
X {
X case '1': /* transport someone */
X tamper = T_TRANSPORT;
X option = "transport";
X break;
X
X case '2': /* curse another */
X tamper = T_CURSED;
X option = "curse";
X break;
X
X case '3': /* create energy void */
X if ((loc = allocvoid()) > 20L * SZ_VOIDSTRUCT)
X /* can only have 20 void active at once */
X mvaddstr(5, 0, "Sorry, void creation limit reached.\n");
X else
X {
X addstr("Enter the X Y coordinates of void ? ");
X getstring(Databuf, SZ_DATABUF);
X sscanf(Databuf, "%F %F", &temp1, &temp2);
X Enrgyvoid.ev_x = floor(temp1);
X Enrgyvoid.ev_y = floor(temp2);
X Enrgyvoid.ev_active = TRUE;
X writevoid(&Enrgyvoid, loc);
X mvaddstr(5, 0, "It is done.\n");
X }
X return;
X
X case '4': /* bestow gold to subject */
X tamper = T_BESTOW;
X addstr("How much gold to bestow ? ");
X temp1 = infloat();
X if (temp1 > Player.p_gold || temp1 < 0)
X {
X mvaddstr(5, 0, "You don't have that !\n");
X return;
X }
X
X Player.p_gold -= floor(temp1);
X option = "give gold to";
X break;
X
X case '5': /* collect accumulated taxes */
X if ((fp = fopen(Goldfile, "r+")) != NULL)
X /* collect taxes */
X {
X fread((char *) &temp1, sizeof(double), 1, fp);
X fseek(fp, 0L, 0);
X /* clear out value */
X temp2 = 0.0;
X fwrite((char *) &temp2, sizeof(double), 1, fp);
X fclose(fp);
X }
X
X mvprintw(4, 0, "You have collected %.0f in gold.\n", temp1);
X Player.p_gold += floor(temp1);
X return;
X
X default:
X return;
X }
X /* end of king options */
X }
X else
X /* council of wise, valar, wizard options */
X {
X addstr("1:Heal ");
X if (Player.p_palantir || Wizard)
X addstr("2:Seek Grail ");
X if (Player.p_specialtype == SC_VALAR || Wizard)
X addstr("3:Throw Monster 4:Relocate 5:Bless ");
X if (Wizard)
X addstr("6:Vaporize ");
X
X ch = getanswer(" ", TRUE);
X if (!Wizard)
X {
X if (ch > '2' && Player.p_specialtype != SC_VALAR)
X {
X ILLCMD();
X return;
X }
X
X if (Player.p_mana < MM_INTERVENE)
X {
X mvaddstr(5, 0, "No mana left.\n");
X return;
X }
X else
X Player.p_mana -= MM_INTERVENE;
X }
X
X switch (ch)
X {
X case '1': /* heal another */
X tamper = T_HEAL;
X option = "heal";
X break;
X
X case '2': /* seek grail */
X if (Player.p_palantir)
X /* need a palantir to seek */
X {
X fseek(Energyvoidfp, 0L, 0);
X fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp);
X temp1 = distance(Player.p_x, Enrgyvoid.ev_x, Player.p_y, Enrgyvoid.ev_y);
X temp1 += ROLL(-temp1 / 10.0, temp1 / 5.0); /* add some error */
X mvprintw(5, 0, "The palantir says the Grail is about %.0f away.\n", temp1);
X }
X else
X /* no palantir */
X mvaddstr(5, 0, "You need a palantir to seek the Grail.\n");
X return;
X
X case '3': /* lob monster at someone */
X mvaddstr(4, 0, "Which monster [0-99] ? ");
X temp1 = infloat();
X temp1 = MAX(0.0, MIN(99.0, temp1));
X tamper = T_MONSTER;
X option = "throw a monster at";
X break;
X
X case '4': /* move another player */
X mvaddstr(4, 0, "New X Y coordinates ? ");
X getstring(Databuf, SZ_DATABUF);
X sscanf(Databuf, "%F %F", &temp1, &temp2);
X tamper = T_RELOCATE;
X option = "relocate";
X break;
X
X case '5': /* bless a player */
X tamper = T_BLESSED;
X option = "bless";
X break;
X
X case '6': /* kill off a player */
X if (Wizard)
X {
X tamper = T_VAPORIZED;
X option = "vaporize";
X break;
X }
X else
X return;
X
X default:
X return;
X }
X
X if (!Wizard)
X Player.p_age += N_AGE; /* penalty for using this stuff */
X /* end of valar, etc. options */
X }
X
X for (;;)
X /* prompt for player to affect */
X {
X mvprintw(4, 0, "Who do you want to %s ? ", option);
X getstring(Databuf, SZ_DATABUF);
X truncstring(Databuf);
X
X if (Databuf[0] == '\0')
X userlist(TRUE);
X else
X break;
X }
X
X if (strcmp(Player.p_name, Databuf) != 0)
X /* name other than self */
X {
X if ((loc = findname(Databuf, &Other)) >= 0L)
X {
X if (Other.p_tampered != T_OFF)
X {
X mvaddstr(5, 0, "That person has something pending already.\n");
X return;
X }
X else
X {
X if (tamper == T_RELOCATE
X && CIRCLE(temp1, temp2) < CIRCLE(Other.p_x, Other.p_y)
X && !Wizard)
X mvaddstr(5, 0, "Cannot move someone closer to the Lord's Chamber.\n");
X else
X {
X Other.p_tampered = tamper;
X Other.p_1scratch = floor(temp1);
X Other.p_2scratch = floor(temp2);
X writerecord(&Other, loc);
X mvaddstr(5, 0, "It is done.\n");
X }
X return;
X }
X }
X else
X /* player not found */
X mvaddstr(5, 0, "There is no one by that name.\n");
X }
X else
X /* self */
X mvaddstr(5, 0, "You may not do it to yourself!\n");
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: writevoid()
X/
X/ FUNCTION: update energy void entry in energy void file
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS:
X/ struct energyvoid *vp - pointer to structure to write to file
X/ long loc - location in file to update
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: fseek(), fwrite(), fflush()
X/
X/ GLOBAL INPUTS: *Energyvoidfp
X/
X/ GLOBAL OUTPUTS: none
X/
X/ DESCRIPTION:
X/ Write out energy void structure at specified location.
X/
X/************************************************************************/
X
Xwritevoid(vp, loc)
Xregister struct energyvoid *vp;
Xlong loc;
X{
X
X fseek(Energyvoidfp, loc, 0);
X fwrite((char *) vp, SZ_VOIDSTRUCT, 1, Energyvoidfp);
X fflush(Energyvoidfp);
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: allocvoid()
X/
X/ FUNCTION: allocate space for a new energy void
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: location of new energy void space
X/
X/ MODULES CALLED: fread(), fseek()
X/
X/ GLOBAL INPUTS: *Energyvoidfp, Enrgyvoid
X/
X/ GLOBAL OUTPUTS: none
X/
X/ DESCRIPTION:
X/ Search energy void file for an inactive entry and return its
X/ location.
X/ If no inactive ones are found, return one more than last location.
X/
X/************************************************************************/
X
Xlong
Xallocvoid()
X{
Xlong loc = 0L; /* location of new energy void */
X
X fseek(Energyvoidfp, 0L, 0);
X while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1)
X if (Enrgyvoid.ev_active)
X loc += SZ_VOIDSTRUCT;
X else
X break;
X
X return(loc);
X}
!EOR!
echo x - gamesupport.c
sed 's/^X//' > gamesupport.c << '!EOR!'
X/*
X * gamesupport.c - auxiliary routines for support of Phantasia
X */
X
X#include "include.h"
X
X/************************************************************************
X/
X/ FUNCTION NAME: changestats()
X/
X/ FUNCTION: examine/change statistics for a player
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS:
X/ bool ingameflag - set if called while playing game (Wizard only)
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: freerecord(), writerecord(), descrstatus(), truncstring(),
X/ time(), more(), wmove(), wclear(), strcmp(), printw(), strcpy(),
X/ infloat(), waddstr(), cleanup(), findname(), userlist(), mvprintw(),
X/ localtime(), getanswer(), descrtype(), getstring()
X/
X/ GLOBAL INPUTS: LINES, *Login, Other, Wizard, Player, *stdscr, Databuf[],
X/ Fileloc
X/
X/ GLOBAL OUTPUTS: Echo
X/
X/ DESCRIPTION:
X/ Prompt for player name to examine/change.
X/ If the name is NULL, print a list of all players.
X/ If we are called from within the game, check for the
X/ desired name being the same as the current player's name.
X/ Only the 'Wizard' may alter players.
X/ Items are changed only if a non-zero value is specified.
X/ To change an item to 0, use 0.1; it will be truncated later.
X/
X/ Players may alter their names and passwords, if the following
X/ are true:
X/ - current login matches the character's logins
X/ - the password is known
X/ - the player is not in the middle of the game (ingameflag == FALSE)
X/
X/ The last condition is imposed for two reasons:
X/ - the game could possibly get a bit hectic if a player were
X/ continually changing his/her name
X/ - another player structure would be necessary to check for names
X/ already in use
X/
X/************************************************************************/
X
Xchangestats(ingameflag)
Xbool ingameflag;
X{
Xstatic char flag[2] = /* for printing values of bools */
X {'F', 'T'};
Xregister struct player *playerp;/* pointer to structure to alter */
Xregister char *prompt; /* pointer to prompt string */
Xint c; /* input */
Xint today; /* day of year of today */
Xint temp; /* temporary variable */
Xlong loc; /* location in player file */
Xlong now; /* time now */
Xdouble dtemp; /* temporary variable */
Xbool *bptr; /* pointer to bool item to change */
Xdouble *dptr; /* pointer to double item to change */
Xshort *sptr; /* pointer to short item to change */
X
X clear();
X
X for (;;)
X /* get name of player to examine/alter */
X {
X mvaddstr(5, 0, "Which character do you want to look at ? ");
X getstring(Databuf, SZ_DATABUF);
X truncstring(Databuf);
X
X if (Databuf[0] == '\0')
X userlist(ingameflag);
X else
X break;
X }
X
X loc = -1L;
X
X if (!ingameflag)
X /* use 'Player' structure */
X playerp = &Player;
X else if (strcmp(Databuf, Player.p_name) == 0)
X /* alter/examine current player */
X {
X playerp = &Player;
X loc = Fileloc;
X }
X else
X /* use 'Other' structure */
X playerp = &Other;
X
X /* find player on file */
X if (loc < 0L && (loc = findname(Databuf, playerp)) < 0L)
X /* didn't find player */
X {
X clear();
X mvaddstr(11, 0, "Not found.");
X return;
X }
X
X time(&now);
X today = localtime(&now)->tm_yday;
X
X clear();
X
X for (;;)
X /* print player structure, and prompt for action */
X {
X mvprintw(0, 0,"A:Name %s\n", playerp->p_name);
X
X if (Wizard)
X printw("B:Password %s\n", playerp->p_password);
X else
X addstr("B:Password XXXXXXXX\n");
X
X printw(" :Login %s\n", playerp->p_login);
X
X printw("C:Experience %.0f\n", playerp->p_experience);
X printw("D:Level %.0f\n", playerp->p_level);
X printw("E:Strength %.0f\n", playerp->p_strength);
X printw("F:Sword %.0f\n", playerp->p_sword);
X printw(" :Might %.0f\n", playerp->p_might);
X printw("G:Energy %.0f\n", playerp->p_energy);
X printw("H:Max-Energy %.0f\n", playerp->p_maxenergy);
X printw("I:Shield %.0f\n", playerp->p_shield);
X printw("J:Quickness %.0f\n", playerp->p_quickness);
X printw("K:Quicksilver %.0f\n", playerp->p_quksilver);
X printw(" :Speed %.0f\n", playerp->p_speed);
X printw("L:Magic Level %.0f\n", playerp->p_magiclvl);
X printw("M:Mana %.0f\n", playerp->p_mana);
X printw("N:Brains %.0f\n", playerp->p_brains);
X
X if (Wizard || playerp->p_specialtype != SC_VALAR)
X mvaddstr(0, 40, descrstatus(playerp));
X
X mvprintw(1, 40, "O:Poison %0.3f\n", playerp->p_poison);
X mvprintw(2, 40, "P:Gold %.0f\n", playerp->p_gold);
X mvprintw(3, 40, "Q:Gem %.0f\n", playerp->p_gems);
X mvprintw(4, 40, "R:Sin %0.3f\n", playerp->p_sin);
X if (Wizard)
X {
X mvprintw(5, 40, "S:X-coord %.0f\n", playerp->p_x);
X mvprintw(6, 40, "T:Y-coord %.0f\n", playerp->p_y);
X }
X else
X {
X mvaddstr(5, 40, "S:X-coord ?\n");
X mvaddstr(6, 40, "T:Y-coord ?\n");
X }
X
X mvprintw(7, 40, "U:Age %ld\n", playerp->p_age);
X mvprintw(8, 40, "V:Degenerated %d\n", playerp->p_degenerated);
X
X mvprintw(9, 40, "W:Type %d (%s)\n",
X playerp->p_type, descrtype(playerp, FALSE) + 1);
X mvprintw(10, 40, "X:Special Type %d\n", playerp->p_specialtype);
X mvprintw(11, 40, "Y:Lives %d\n", playerp->p_lives);
X mvprintw(12, 40, "Z:Crowns %d\n", playerp->p_crowns);
X mvprintw(13, 40, "0:Charms %d\n", playerp->p_charms);
X mvprintw(14, 40, "1:Amulets %d\n", playerp->p_amulets);
X mvprintw(15, 40, "2:Holy Water %d\n", playerp->p_holywater);
X
X temp = today - playerp->p_lastused;
X if (temp < 0)
X /* last year */
X temp += 365;
X mvprintw(16, 40, "3:Lastused %d (%d)\n", playerp->p_lastused, temp);
X
X mvprintw(18, 8, "4:Blessed %c 5:Palantir %c 6:Virgin %c 7:Blind %c",
X flag[playerp->p_palantir],
X flag[playerp->p_blessing],
X flag[playerp->p_virgin],
X flag[playerp->p_blindness]);
X
X if (!Wizard)
X mvprintw(19, 8, "8:Ring %c",
X flag[playerp->p_ring.ring_type != R_NONE]);
X else
X mvprintw(19, 8, "8:Ring %d 9:Duration %d",
X playerp->p_ring.ring_type, playerp->p_ring.ring_duration);
X
X if (!Wizard
X /* not wizard */
X && (ingameflag || strcmp(Login, playerp->p_login) != 0))
X /* in game or not examining own character */
X {
X if (ingameflag)
X {
X more(LINES - 1);
X clear();
X return;
X }
X else
X cleanup(TRUE);
X /*NOTREACHED*/
X }
X
X mvaddstr(20, 0, "!:Quit ?:Delete");
X mvaddstr(21, 0, "What would you like to change ? ");
X
X if (Wizard)
X c = getanswer(" ", TRUE);
X else
X /* examining own player; allow to change name and password */
X c = getanswer("!BA", FALSE);
X
X switch (c)
X {
X case 'A': /* change name */
X case 'B': /* change password */
X if (!Wizard)
X /* prompt for password */
X {
X mvaddstr(23, 0, "Password ? ");
X Echo = FALSE;
X getstring(Databuf, 9);
X Echo = TRUE;
X if (strcmp(Databuf, playerp->p_password) != 0)
X continue;
X }
X
X if (c == 'A')
X /* get new name */
X {
X mvaddstr(23, 0, "New name: ");
X getstring(Databuf, SZ_NAME);
X truncstring(Databuf);
X if (Databuf[0] != '\0')
X if (Wizard || findname(Databuf, &Other) < 0L)
X strcpy(playerp->p_name, Databuf);
X }
X else
X /* get new password */
X {
X if (!Wizard)
X Echo = FALSE;
X
X do
X /* get two copies of new password until they match */
X {
X /* get first copy */
X mvaddstr(23, 0, "New password ? ");
X getstring(Databuf, SZ_PASSWORD);
X if (Databuf[0] == '\0')
X break;
X
X /* get second copy */
X mvaddstr(23, 0, "One more time ? ");
X getstring(playerp->p_password, SZ_PASSWORD);
X }
X while (strcmp(playerp->p_password, Databuf) != 0);
X
X Echo = TRUE;
X }
X
X continue;
X
X case 'C': /* change experience */
X prompt = "experience";
X dptr = &playerp->p_experience;
X goto DALTER;
X
X case 'D': /* change level */
X prompt = "level";
X dptr = &playerp->p_level;
X goto DALTER;
X
X case 'E': /* change strength */
X prompt = "strength";
X dptr = &playerp->p_strength;
X goto DALTER;
X
X case 'F': /* change swords */
X prompt = "sword";
X dptr = &playerp->p_sword;
X goto DALTER;
X
X case 'G': /* change energy */
X prompt = "energy";
X dptr = &playerp->p_energy;
X goto DALTER;
X
X case 'H': /* change maximum energy */
X prompt = "max energy";
X dptr = &playerp->p_maxenergy;
X goto DALTER;
X
X case 'I': /* change shields */
X prompt = "shield";
X dptr = &playerp->p_shield;
X goto DALTER;
X
X case 'J': /* change quickness */
X prompt = "quickness";
X dptr = &playerp->p_quickness;
X goto DALTER;
X
X case 'K': /* change quicksilver */
X prompt = "quicksilver";
X dptr = &playerp->p_quksilver;
X goto DALTER;
X
X case 'L': /* change magic */
X prompt = "magic level";
X dptr = &playerp->p_magiclvl;
X goto DALTER;
X
X case 'M': /* change mana */
X prompt = "mana";
X dptr = &playerp->p_mana;
X goto DALTER;
X
X case 'N': /* change brains */
X prompt = "brains";
X dptr = &playerp->p_brains;
X goto DALTER;
X
X case 'O': /* change poison */
X prompt = "poison";
X dptr = &playerp->p_poison;
X goto DALTER;
X
X case 'P': /* change gold */
X prompt = "gold";
X dptr = &playerp->p_gold;
X goto DALTER;
X
X case 'Q': /* change gems */
X prompt = "gems";
X dptr = &playerp->p_gems;
X goto DALTER;
X
X case 'R': /* change sin */
X prompt = "sin";
X dptr = &playerp->p_sin;
X goto DALTER;
X
X case 'S': /* change x coord */
X prompt = "x";
X dptr = &playerp->p_x;
X goto DALTER;
X
X case 'T': /* change y coord */
X prompt = "y";
X dptr = &playerp->p_y;
X goto DALTER;
X
X case 'U': /* change age */
X mvprintw(23, 0, "age = %ld; age = ", playerp->p_age);
X dtemp = infloat();
X if (dtemp != 0.0)
X playerp->p_age = (long) dtemp;
X continue;
X
X case 'V': /* change degen */
X mvprintw(23, 0, "degen = %d; degen = ", playerp->p_degenerated);
X dtemp = infloat();
X if (dtemp != 0.0)
X playerp->p_degenerated = (int) dtemp;
X continue;
X
X case 'W': /* change type */
X prompt = "type";
X sptr = &playerp->p_type;
X goto SALTER;
X
X case 'X': /* change special type */
X prompt = "special type";
X sptr = &playerp->p_specialtype;
X goto SALTER;
X
X case 'Y': /* change lives */
X prompt = "lives";
X sptr = &playerp->p_lives;
X goto SALTER;
X
X case 'Z': /* change crowns */
X prompt = "crowns";
X sptr = &playerp->p_crowns;
X goto SALTER;
X
X case '0': /* change charms */
X prompt = "charm";
X sptr = &playerp->p_charms;
X goto SALTER;
X
X case '1': /* change amulet */
X prompt = "amulet";
X sptr = &playerp->p_amulets;
X goto SALTER;
X
X case '2': /* change holy water */
X prompt = "holy water";
X sptr = &playerp->p_holywater;
X goto SALTER;
X
X case '3': /* change last-used */
X prompt = "last-used";
X sptr = &playerp->p_lastused;
X goto SALTER;
X
X case '4': /* change palantir */
X prompt = "palantir";
X bptr = &playerp->p_palantir;
X goto BALTER;
X
X case '5': /* change blessing */
X prompt = "blessing";
X bptr = &playerp->p_blessing;
X goto BALTER;
X
X case '6': /* change virgin */
X prompt = "virgin";
X bptr = &playerp->p_virgin;
X goto BALTER;
X
X case '7': /* change blindness */
X prompt = "blindness";
X bptr = &playerp->p_blindness;
X goto BALTER;
X
X case '8': /* change ring type */
X prompt = "ring-type";
X sptr = &playerp->p_ring.ring_type;
X goto SALTER;
X
X case '9': /* change ring duration */
X prompt = "ring-duration";
X sptr = &playerp->p_ring.ring_duration;
X goto SALTER;
X
X case '!': /* quit, update */
X if (Wizard &&
X (!ingameflag || playerp != &Player))
X /* turn off status if not modifying self */
X {
X playerp->p_status = S_OFF;
X playerp->p_tampered = T_OFF;
X }
X
X writerecord(playerp, loc);
X clear();
X return;
X
X case '?': /* delete player */
X if (ingameflag && playerp == &Player)
X /* cannot delete self */
X continue;
X
X freerecord(playerp, loc);
X clear();
X return;
X
X default:
X continue;
X }
XDALTER:
X mvprintw(23, 0, "%s = %f; %s = ", prompt, *dptr, prompt);
X dtemp = infloat();
X if (dtemp != 0.0)
X *dptr = dtemp;
X continue;
X
XSALTER:
X mvprintw(23, 0, "%s = %d; %s = ", prompt, *sptr, prompt);
X dtemp = infloat();
X if (dtemp != 0.0)
X *sptr = (short) dtemp;
X continue;
X
XBALTER:
X mvprintw(23, 0, "%s = %c; %s = ", prompt, flag[*bptr], prompt);
X c = getanswer("\nTF", TRUE);
X if (c == 'T')
X *bptr = TRUE;
X else if (c == 'F')
X *bptr = FALSE;
X continue;
X }
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: monstlist()
X/
X/ FUNCTION: print a monster listing
X/
X/ AUTHOR: E. A. Estes, 2/27/86
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: puts(), fread(), fseek(), printf()
X/
X/ GLOBAL INPUTS: Curmonster, *Monstfp
X/
X/ GLOBAL OUTPUTS: none
X/
X/ DESCRIPTION:
X/ Read monster file, and print a monster listing on standard output.
X/
X/************************************************************************/
X
Xmonstlist()
X{
Xregister int count = 0; /* count in file */
X
X puts(" #) Name Str Brain Quick Energy Exper Treas Type Flock%\n");
X fseek(Monstfp, 0L, 0);
X while (fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp) == 1)
X printf("%2d) %-20.20s%4.0f %4.0f %2.0f %5.0f %5.0f %2d %2d %3.0f\n", count++,
X Curmonster.m_name, Curmonster.m_strength, Curmonster.m_brains,
X Curmonster.m_speed, Curmonster.m_energy, Curmonster.m_experience,
X Curmonster.m_treasuretype, Curmonster.m_type, Curmonster.m_flock);
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: scorelist()
X/
X/ FUNCTION: print player score board
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: fread(), fopen(), printf(), fclose()
X/
X/ GLOBAL INPUTS: Scorefile[]
X/
X/ GLOBAL OUTPUTS: none
X/
X/ DESCRIPTION:
X/ Read the scoreboard file and print the contents.
X/
X/************************************************************************/
X
Xscorelist()
X{
Xstruct scoreboard sbuf; /* for reading entries */
Xregister FILE *fp; /* to open the file */
X
X if ((fp = fopen(Scorefile, "r")) != NULL)
X {
X while (fread((char *) &sbuf, SZ_SCORESTRUCT, 1, fp) == 1)
X printf("%-20s (%-9s) Level: %6.0f Type: %s\n",
X sbuf.sb_name, sbuf.sb_login, sbuf.sb_level, sbuf.sb_type);
X fclose(fp);
X }
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: activelist()
X/
X/ FUNCTION: print list of active players to standard output
X/
X/ AUTHOR: E. A. Estes, 3/7/86
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: descrstatus(), fread(), fseek(), printf(), descrtype()
X/
X/ GLOBAL INPUTS: Other, *Playersfp
X/
X/ GLOBAL OUTPUTS: none
X/
X/ DESCRIPTION:
X/ Read player file, and print list of active records to standard output.
X/
X/************************************************************************/
X
Xactivelist()
X{
X fseek(Playersfp, 0L, 0);
X printf("Current characters on file are:\n\n");
X
X while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
X if (Other.p_status != S_NOTUSED)
X printf("%-20s (%-9s) Level: %6.0f %s (%s)\n",
X Other.p_name, Other.p_login, Other.p_level,
X descrtype(&Other, FALSE), descrstatus(&Other));
X
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: purgeoldplayers()
X/
X/ FUNCTION: purge inactive players from player file
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: freerecord(), time(), fread(), fseek(), localtime()
X/
X/ GLOBAL INPUTS: Other, *Playersfp
X/
X/ GLOBAL OUTPUTS: none
X/
X/ DESCRIPTION:
X/ Delete characters which have not been used with the last
X/ three weeks.
X/
X/************************************************************************/
X
Xpurgeoldplayers()
X{
Xint today; /* day of year for today */
Xint daysold; /* how many days since the character has been used */
Xlong ltime; /* time in seconds */
Xlong loc = 0L; /* location in file */
X
X time(<ime);
X today = localtime(<ime)->tm_yday;
X
X for (;;)
X {
X fseek(Playersfp, loc, 0);
X if (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) != 1)
X break;
X
X daysold = today - Other.p_lastused;
X if (daysold < 0)
X daysold += 365;
X
X if (daysold > N_DAYSOLD)
X /* player hasn't been used in a while; delete */
X freerecord(&Other, loc);
X
X loc += SZ_PLAYERSTRUCT;
X }
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: enterscore()
X/
X/ FUNCTION: enter player into scoreboard
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: fread(), fseek(), fopen(), error(), strcmp(), fclose(),
X/ strcpy(), fwrite(), descrtype()
X/
X/ GLOBAL INPUTS: Player, Scorefile[]
X/
X/ GLOBAL OUTPUTS: none
X/
X/ DESCRIPTION:
X/ The scoreboard keeps track of the highest character on a
X/ per-login basis.
X/ Search the scoreboard for an entry for the current login,
X/ if an entry is found, and it is lower than the current player,
X/ replace it, otherwise create an entry.
X/
X/************************************************************************/
X
Xenterscore()
X{
Xstruct scoreboard sbuf; /* buffer to read in scoreboard entries */
XFILE *fp; /* to open scoreboard file */
Xlong loc = 0L; /* location in scoreboard file */
Xbool found = FALSE; /* set if we found an entry for this login */
X
X if ((fp = fopen(Scorefile, "r+")) != NULL)
X {
X while (fread((char *) &sbuf, SZ_SCORESTRUCT, 1, fp) == 1)
X if (strcmp(Player.p_login, sbuf.sb_login) == 0)
X {
X found = TRUE;
X break;
X }
X else
X loc += SZ_SCORESTRUCT;
X }
X else
X {
X error(Scorefile);
X /*NOTREACHED*/
X }
X
X /*
X * At this point, 'loc' will either indicate a point beyond
X * the end of file, or the place where the previous entry
X * was found.
X */
X
X if ((!found) || Player.p_level > sbuf.sb_level)
X /* put new entry in for this login */
X {
X strcpy(sbuf.sb_login, Player.p_login);
X strcpy(sbuf.sb_name, Player.p_name);
X sbuf.sb_level = Player.p_level;
X strcpy(sbuf.sb_type, descrtype(&Player, TRUE));
X }
X
X /* update entry */
X fseek(fp, loc, 0);
X fwrite((char *) &sbuf, SZ_SCORESTRUCT, 1, fp);
X fclose(fp);
X}
!EOR!
echo x - io.c
sed 's/^X//' > io.c << '!EOR!'
X/*
X * io.c - input/output routines for Phantasia
X */
X
X#include "include.h"
X
X/************************************************************************
X/
X/ FUNCTION NAME: getstring()
X/
X/ FUNCTION: read a string from operator
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS:
X/ char *cp - pointer to buffer area to fill
X/ int mx - maximum number of characters to put in buffer
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
X/ wclrtoeol()
X/
X/ GLOBAL INPUTS: Echo, _iob[], Wizard, *stdscr
X/
X/ GLOBAL OUTPUTS: _iob[]
X/
X/ DESCRIPTION:
X/ Read a string from the keyboard.
X/ This routine is specially designed to:
X/
X/ - strip non-printing characters (unless Wizard)
X/ - echo, if desired
X/ - redraw the screen if CH_REDRAW is entered
X/ - read in only 'mx - 1' characters or less characters
X/ - nul-terminate string, and throw away newline
X/
X/ 'mx' is assumed to be at least 2.
X/
X/************************************************************************/
X
Xgetstring(cp, mx)
Xregister char *cp;
Xregister int mx;
X{
Xregister char *inptr; /* pointer into string for next string */
Xint x, y; /* original x, y coordinates on screen */
Xint ch; /* input */
X
X getyx(stdscr, y, x); /* get coordinates on screen */
X inptr = cp;
X *inptr = '\0'; /* clear string to start */
X --mx; /* reserve room in string for nul terminator */
X
X do
X /* get characters and process */
X {
X if (Echo)
X mvaddstr(y, x, cp); /* print string on screen */
X clrtoeol(); /* clear any data after string */
X refresh(); /* update screen */
X
X ch = getchar(); /* get character */
X
X switch (ch)
X {
X case CH_ERASE: /* back up one character */
X if (inptr > cp)
X --inptr;
X break;
X
X case CH_KILL: /* back up to original location */
X inptr = cp;
X break;
X
X case CH_NEWLINE: /* terminate string */
X break;
X
X case CH_REDRAW: /* redraw screen */
X clearok(stdscr, TRUE);
X continue;
X
X default: /* put data in string */
X if (ch >= ' ' || Wizard)
X /* printing char; put in string */
X *inptr++ = ch;
X }
X
X *inptr = '\0'; /* terminate string */
X }
X while (ch != CH_NEWLINE && inptr < cp + mx);
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: more()
X/
X/ FUNCTION: pause and prompt player
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS:
X/ int where - line on screen on which to pause
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: wmove(), waddstr(), getanswer()
X/
X/ GLOBAL INPUTS: *stdscr
X/
X/ GLOBAL OUTPUTS: none
X/
X/ DESCRIPTION:
X/ Print a message, and wait for a space character.
X/
X/************************************************************************/
X
Xmore(where)
Xint where;
X{
X mvaddstr(where, 0, "-- more --");
X getanswer(" ", FALSE);
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: infloat()
X/
X/ FUNCTION: input a floating point number from operator
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: floating point number from operator
X/
X/ MODULES CALLED: sscanf(), getstring()
X/
X/ GLOBAL INPUTS: Databuf[]
X/
X/ GLOBAL OUTPUTS: none
X/
X/ DESCRIPTION:
X/ Read a string from player, and scan for a floating point
X/ number.
X/ If no valid number is found, return 0.0.
X/
X/************************************************************************/
X
Xdouble
Xinfloat()
X{
Xdouble result; /* return value */
X
X getstring(Databuf, SZ_DATABUF);
X if (sscanf(Databuf, "%F", &result) < 1)
X /* no valid number entered */
X result = 0.0;
X
X return(result);
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: inputoption()
X/
X/ FUNCTION: input an option value from player
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: floor(), random(), getanswer()
X/
X/ GLOBAL INPUTS: Player
X/
X/ GLOBAL OUTPUTS: Player
X/
X/ DESCRIPTION:
X/ Age increases with every move.
X/ Refresh screen, and get a single character option from player.
X/ Return a random value if player's ring has gone bad.
X/
X/************************************************************************/
X
Xinputoption()
X{
X ++Player.p_age; /* increase age */
X
X if (Player.p_ring.ring_type != R_SPOILED)
X /* ring ok */
X return(getanswer("T ", TRUE));
X else
X /* bad ring */
X {
X getanswer(" ", TRUE);
X return((int) ROLL(0.0, 5.0) + '0');
X }
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: interrupt()
X/
X/ FUNCTION: handle interrupt from operator
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: fork(), exit(), wait(), death(), alarm(), execl(), wmove(),
X/ getgid(), signal(), getenv(), wclear(), setuid(), getuid(), setgid(),
X/ crmode(), clearok(), waddstr(), cleanup(), wrefresh(), leavegame(),
X/ getanswer()
X/
X/ GLOBAL INPUTS: Player, *stdscr
X/
X/ GLOBAL OUTPUTS: none
X/
X/ DESCRIPTION:
X/ Allow player to quit upon hitting the interrupt key.
X/ If the player wants to quit while in battle, he/she automatically
X/ dies.
X/ If SHELL is defined, spawn a shell if the if the question is
X/ answered with a '!'.
X/ We are careful to save the state of the screen, and return it
X/ to its original condition.
X/
X/************************************************************************/
X
Xinterrupt()
X{
Xchar line[81]; /* a place to store data already on screen */
Xregister int loop; /* counter */
Xint x, y; /* coordinates on screen */
Xint ch; /* input */
Xunsigned savealarm; /* to save alarm value */
X#ifdef SHELL
Xregister char *shell; /* pointer to shell to spawn */
Xint childpid; /* pid of spawned process */
X#endif
X
X#ifdef SYS3
X signal(SIGINT, SIG_IGN);
X#endif
X#ifdef SYS5
X signal(SIGINT, SIG_IGN);
X#endif
X
X savealarm = alarm(0); /* turn off any alarms */
X
X getyx(stdscr, y, x); /* save cursor location */
X
X for (loop = 0; loop < 80; ++loop) /* save line on screen */
X {
X move(4, loop);
X line[loop] = inch();
X }
X line[80] = '\0'; /* nul terminate */
X
X if (Player.p_status == S_INBATTLE || Player.p_status == S_MONSTER)
X /* in midst of fighting */
X {
X mvaddstr(4, 0, "Quitting now will automatically kill your character. Still want to ? ");
X#ifdef SHELL
X ch = getanswer("NY!", FALSE);
X#else
X ch = getanswer("NY", FALSE);
X#endif
X if (ch == 'Y')
X death("Bailing out");
X /*NOTREACHED*/
X }
X else
X {
X#ifdef SHELL
X mvaddstr(4, 0, "Do you really want to quit [! = Shell] ? ");
X ch = getanswer("NY!", FALSE);
X#else
X mvaddstr(4, 0, "Do you really want to quit ? ");
X ch = getanswer("NY", FALSE);
X#endif
X if (ch == 'Y')
X leavegame();
X /*NOTREACHED*/
X }
X
X#ifdef SHELL
X if (ch == '!')
X /* shell escape */
X {
X if ((shell = getenv("SHELL")) == NULL)
X /* use default */
X shell = SHELL;
X
X if ((childpid = fork()) == 0)
X /* in child */
X {
X clear();
X refresh();
X cleanup(FALSE); /* out of curses, close files */
X
X setuid(getuid()); /* make sure we are running with real uid */
X setgid(getgid()); /* make sure we are running with real gid */
X execl(shell, shell, "-i", 0);
X execl(SHELL, SHELL, "-i", 0); /* last resort */
X
X exit(0);
X /*NOTREACHED*/
X }
X else
X /* in parent */
X {
X while (wait((int *) NULL) != childpid); /* wait until done */
X crmode(); /* restore keyboard */
X clearok(stdscr, TRUE); /* force redraw of screen */
X }
X }
X#endif
X
X mvaddstr(4, 0, line); /* restore data on screen */
X move(y, x); /* restore cursor */
X refresh();
X
X#ifdef SYS3
X signal(SIGINT, interrupt);
X#endif
X#ifdef SYS5
X signal(SIGINT, interrupt);
X#endif
X
X alarm(savealarm); /* restore alarm */
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: getanswer()
X/
X/ FUNCTION: get an answer from operator
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS:
X/ char *choices - string of (upper case) valid choices
X/ bool def - set if default answer
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: alarm(), wmove(), waddch(), signal(), setjmp(), strchr(),
X/ _filbuf(), clearok(), toupper(), wrefresh(), mvprintw(), wclrtoeol()
X/
X/ GLOBAL INPUTS: catchalarm(), Echo, _iob[], _ctype[], *stdscr, Timeout,
X/ Timeoenv[]
X/
X/ GLOBAL OUTPUTS: _iob[]
X/
X/ DESCRIPTION:
X/ Get a single character answer from operator.
X/ Timeout waiting for response. If we timeout, or the
X/ answer in not in the list of valid choices, print choices,
X/ and wait again, otherwise return the first character in ths
X/ list of choices.
X/ Give up after 3 tries.
X/
X/************************************************************************/
X
Xgetanswer(choices, def)
Xchar *choices;
Xbool def;
X{
Xint ch; /* input */
Xint loop; /* counter */
Xint oldx, oldy; /* original coordinates on screen */
X
X getyx(stdscr, oldy, oldx);
X alarm(0); /* make sure alarm is off */
X
X for (loop = 3; loop; --loop)
X /* try for 3 times */
X {
X if (setjmp(Timeoenv) != 0)
X /* timed out waiting for response */
X {
X if (def || loop <= 1)
X /* return default answer */
X break;
X else
X /* prompt, and try again */
X goto YELL;
X }
X else
X /* wait for response */
X {
X clrtoeol();
X refresh();
X#ifdef BSD41
X sigset(SIGALRM, catchalarm);
X#else
X signal(SIGALRM, catchalarm);
X#endif
X /* set timeout */
X if (Timeout)
X alarm(7); /* short */
X else
X alarm(600); /* long */
X
X ch = getchar();
X
X alarm(0); /* turn off timeout */
X
X if (ch < 0)
X /* caught some signal */
X {
X ++loop;
X continue;
X }
X else if (ch == CH_REDRAW)
X /* redraw screen */
X {
X clearok(stdscr, TRUE); /* force clear screen */
X ++loop; /* don't count this input */
X continue;
X }
X else if (Echo)
X {
X addch(ch); /* echo character */
X refresh();
X }
X
X if (islower(ch))
X /* convert to upper case */
X ch = toupper(ch);
X
X if (def || strchr(choices, ch) != NULL)
X /* valid choice */
X return(ch);
X else if (!def && loop > 1)
X /* bad choice; prompt, and try again */
X {
XYELL: mvprintw(oldy + 1, 0, "Please choose one of : [%s]\n", choices);
X move(oldy, oldx);
X clrtoeol();
X continue;
X }
X else
X /* return default answer */
X break;
X }
X }
X
X return(*choices);
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: catchalarm()
X/
X/ FUNCTION: catch timer when waiting for input
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: longjmp()
X/
X/ GLOBAL INPUTS: Timeoenv[]
X/
X/ GLOBAL OUTPUTS: none
X/
X/ DESCRIPTION:
X/ Come here when the alarm expires while waiting for input.
X/ Simply longjmp() into getanswer().
X/
X/************************************************************************/
X
Xcatchalarm()
X{
X longjmp(Timeoenv, 1);
X}
!EOR!